package ca.bcit.comp3910.access;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.TreeMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.enterprise.context.ApplicationScoped;
import javax.inject.Inject;
import javax.inject.Named;
import javax.sql.DataSource;

import ca.bcit.comp3910.model.Employee;

/**
 * CRUD for Employee class
 * 
 * @author Ivy Cheung, Stacy Mitchell
 * @version 2.0
 * 
 */
@SuppressWarnings("serial")
@Named
@ApplicationScoped
public class EmployeeManager implements Serializable {
	/**
	 * Datasource
	 */
    @Resource(mappedName = "java:jboss/datasources/assignment")
    private DataSource dataSource;
    /**
     * Inject employee bean
     */
    @Inject
    Employee employee;
    /**
     * Map to hold Employee ID (key), Employee data (value)
     */
    Map<Integer, Employee> map = new TreeMap<Integer, Employee>();
    /**
     * Is user is logged in
     */
    boolean loggedIn = false;
    
    /**
     * Post Construct
     * Load users from database for testing purposes
     */
    @PostConstruct
    public void onCreate() {
        map.clear();
        PreparedStatement stmt = null;
        Connection connection = null;
        try {
        	connection = dataSource.getConnection();
        	stmt = connection.prepareStatement("SELECT * FROM users");
            try {
            	ResultSet rs = stmt.executeQuery();
            	while (rs.next()) {
            		int empID = rs.getInt("EmployeeID");
                    String empPassword = rs.getString("EmployeePassword");
                    String empName = rs.getString("EmployeeName");
                    boolean superuser = rs.getBoolean("Superuser");
                    Employee employee = new Employee(empID, empPassword, empName, superuser);
                    map.put(empID, employee);
            	}
            } finally {
            	if (stmt != null) {
            		stmt.close();
            	}
            }
        } catch (SQLException e) {
			e.printStackTrace();
		} finally {
        	if (connection != null) {
        		try {
					connection.close();
				} catch (SQLException e) {
					e.printStackTrace();
				}
        	}
        }  
}
    
    /**
     * Create Employee
     * 
     * @param empID - employee ID
     * @param emp - employee object
     * @return true - if employee has been created; false - error, etc
     */
    public boolean createEmployee(int empID, Employee emp) {
        if (!map.containsKey(empID)) {
            map.put(empID, emp);
        	PreparedStatement stmt = null;
            Connection connection = null;
            try {
                try {
                    connection = dataSource.getConnection();
                    try {
                        stmt = connection.prepareStatement("INSERT INTO users " +
                                "VALUES (?,?,?,?)");
                                stmt.setInt(1, empID);
                                stmt.setString(2, emp.getPassword());
                                stmt.setString(3, emp.getEmpName());
                                stmt.setBoolean(4, emp.isSuperUser());
                                stmt.executeUpdate();
                    } finally {
                        if (stmt != null) {
                            stmt.close();
                        }
                    }
                } finally {
                    if (connection != null) {
                        connection.close();
                    }
                }
            } catch (SQLException ex) {
                System.out.println("Error in addUser()");
                ex.printStackTrace();
                System.out.println("Statement was: " + stmt.toString());
            }
            return true;
        }
        return false;
    }

    /**
     * Update Employee
     * 
     * @param empID - employee ID
     * @param emp - employee object
     * @return true - if employee has been updated
     */

    public boolean updateEmployee(int empID, Employee emp) {
        PreparedStatement stmt = null;
    	Connection connection = null;
    	try {
    		try {
    			connection = dataSource.getConnection();
    			try {
    				stmt = connection.prepareStatement("UPDATE users SET EmployeeID = ?, " +
    											"EmployeePassword = ?, EmployeeName = ?, " +
    											"Superuser = ? " + "WHERE EmployeeID = ?");
    				stmt.setInt(1, empID);
    				stmt.setString(2, emp.getPassword());
    				stmt.setString(3, emp.getEmpName());
    				stmt.setBoolean(4, emp.isSuperUser());
    				stmt.setInt(5, empID);
    				stmt.executeUpdate();
    				map.put(empID, emp);
    				return true;
    			} finally {
    				if (stmt != null) {
    					stmt.close();
    				}
    			}
    		} finally {
    			if (connection != null) {
    				connection.close();
    			}
    		}
    	} catch (SQLException ex) {
    		System.out.println("Error in delete ");
    		ex.printStackTrace();
    	}
        return false;
    }

    /**
     * Delete employee
     * 
     * @param empID - employee ID
     * @return true - if employee has been deleted; false - error, etc
     */
    public boolean deleteEmployee(int empID) {
    	PreparedStatement stmt = null;
    	Connection connection = null;
    	try {
    		try {
    			connection = dataSource.getConnection();
    			try {
    				stmt = connection.prepareStatement("DELETE FROM users WHERE EmployeeID = ?");
    				stmt.setInt(1, empID);
    				stmt.executeUpdate();
    				map.remove(empID);
    				return true;
    			} finally {
    				if (stmt != null) {
    					stmt.close();
    				}
    			}
    		} finally {
    			if (connection != null) {
    				connection.close();
    			}
    		}
    	} catch (SQLException ex) {
    		System.out.println("Error in delete ");
    		ex.printStackTrace();
    	}
        return false;
}

    /**
     * If user is admin
     * 
     * @param empID - emp ID
     * @return true - if employee is admin; false - is employee
     */
    public boolean isSuperUser(int empID) {
        if (map.containsKey(empID)) {
            Employee temp = map.get(empID);
            if (temp.isSuperUser()) {
                return true;
            }
        }
        return false;
    }

    /**
     * Check Password
     * 
     * @param empID - emp ID
     * @param password - password
     * @return true if successful - false cannot log in
     */
    public boolean checkPassword(int empID, String password) {
        if (map.containsKey(empID)) {
            Employee temp = map.get(empID);
            if (temp.getPassword().equals(password)) {
                return true;
            }
        } else {
            return false;
        }
        return false;
    }
    

    public boolean isLoggedIn() { return loggedIn; }

	public void setLoggedIn(boolean loggedIn) {	this.loggedIn = loggedIn; }

	/**
     * Store current user
     * 
     * @param empID - id
     */
    public void setEmployee(int empID) {
        employee = map.get(empID);
        setLoggedIn(true);
    }

    /**
     * Get current user
     * 
     * @return employee
     */
    public Employee getEmployee() {
        return employee;
    }

    /**
     * Get all employee IDs
     * 
     * @return arraylist of employee ids
     */
    public ArrayList<Employee> getAllEmpID() {
        ArrayList<Employee> idList = new ArrayList<Employee>();
        for (Entry<Integer, Employee> entry : map.entrySet()) {
            idList.add(entry.getValue());
        }
        return idList;
    }

}
